<template>
  <div>
    <el-tree
      ref="tree"
      :nodeKey="nodeKey"
      :data="myData"
      :props="props"
      @check-change="handleCheckChange"
      :style="styleCss"
      :filter-node-method="filterNodeMethod"
      @node-click="handleNodeClick"
      :default-checked-keys="defaultCheckedKeys"
      :default-expand-all="defaultExpandAll"
      :lazy="lazy"
      :check-on-click-node="checkOnClickNode" 
      :expand-on-click-node="expandOnClickNode"
      :check-strictly="checkStrictly"
      @node-contextmenu="rightClick"
      :showCheckbox="showCheckbox"
      :render-content="renderContent"
    >
    </el-tree>

    <div
      v-if="rightMenu"
      v-show="menuVisible"
      @mouseleave="menuVisible = !menuVisible"
      class="dev-type-main-left"
    >
      <ul id="menu" class="right-menu">
        <li
          tabindex="-1"
          class="menu-item"
          id="menu-4994-1-0"
          @click="() => treeAdd(nodeData)"
        >
          <el-link icon="el-icon-circle-plus-outline" :underline="false"
            >添加</el-link
          >
        </li>
        <li
          tabindex="-1"
          class="menu-item"
          id="menu-4994-1-0"
          @click="() => treeEdit(nodeData)"
        >
          <el-link icon="el-icon-edit" :underline="false">编辑</el-link>
        </li>
        <li
          tabindex="-1"
          class="menu-item"
          id="menu-4994-1-2"
          @click="() => treeRemove(nodeData)"
        >
          <el-link icon="el-icon-delete" :underline="false">删除</el-link>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name: "TreeMenu",
  data() {
    return {
      myData: [],
      menuVisible: false,
    };
  },
  props: {
    styleCss: String,
    value: [String, Number, Array],
    enableAll: {
      type: Boolean,
      default: true,
    },
    rightMenu: {
      type: Boolean,
      default: false,
    },
    data: Array,
    emptyText: String,
    renderAfterExpand: Boolean,
    nodeKey: String,
    checkStrictly: Boolean,
    defaultExpandAll: {
      type: Boolean,
      default: false,
    },
    expandOnClickNode: {
      type: Boolean,
      default() {
        return false;
      },
    },
    checkOnClickNode:{
      type: Boolean,
      default() {
        return false;
      },
    },
    checkDescendants: Boolean,
    autoExpandParent: Boolean,
    defaultCheckedKeys: Array,
    defaultExpandedKeys: {
      type: Array,
      default() {
        return [""];
      },
    },
    renderContent: Function,
    showCheckbox: Boolean,
    draggable: Boolean,
    allowDrag: Function,
    allowDrop: Function,
    props: {
      default() {
        return {
          children: "children",
          label: "label",
          icon: "icon",
          disabled: "disabled",
        };
      },
    },
    lazy: Boolean,
    checkStrictly: {
      type: Boolean,
      default: false,
    },
    highlightCurrent: {
      type: Boolean,
      default: true,
    },
    load: Function,
    filterNodeMethod: Function,
    accordion: Boolean,
    indent: Number,
    showCheckbox: {
      type: Boolean,
      default() {
        return false;
      },
    },
    ignorePrefix: {
      type: String,
      default: "[Menu]",
    },
  },
  watch: {
    data: {
      nodeData: {},
      immediate: true,
      handler(val) {
        this.myData = this.data;
        // this.myData = this.getMyData();

        this.value = this.value;
      },
    },
    value: {
      immediate: true,
      deep: true,
      handler(val) {
        if (this.nodeKey) {
          this.$nextTick(() => {
            if (Object.prototype.toString.call(val) !== "[object Array]") {
              this.$refs.tree.setCurrentKey(val);
            } else {
              let listKey = [];

              val.forEach((item) => {
                listKey.push(item[this.nodeKey]);
              });

              this.$refs.tree.setCheckedKeys(listKey);
            }
          });
        }
      },
    },
  },
  computed: {
    myProps() {
      return {
        children: this.props.children || "children",
        label: this.props.label || "label",
        icon: this.props.icon || "icon",
        disabled: this.props.disabled || "disabled",
        parentNodeKey: this.props.parentNodeKey || "ParentId",
      };
    },
  },
  created() {},
  methods: {
    // 树形右键事件
    rightClick(MouseEvent, object, Node, element) {
      if (!this.rightMenu) {
        return;
      }
      if (Node.data[this.nodeKey] == "-1") {
        return;
      }
      this.nodeData = Node.data;

      this.menuVisible = true;
      let menu = document.querySelector("#menu");
      menu.style.cssText =
        "position: fixed; left: " +
        (MouseEvent.clientX - 10) +
        "px" +
        "; top: " +
        (MouseEvent.clientY - 18) +
        "px; z-index: 999; cursor:pointer;";
    },
    // 树形添加
    treeAdd() {
      this.$emit("right-Add", this.nodeData);
    },
    // 树形编辑
    treeEdit() {
      this.$emit("right-Edit", this.nodeData);
    },
    // 树形删除
    treeRemove() {
      if (this.nodeKey && this.showCheckbox) {
        // 获取当前选中
        let checkIds = this.$refs.tree.getCheckedKeys();
        this.$refs.tree.setCheckedKeys([]);

        // 选中当前右键节点
        let id = this.nodeData[this.nodeKey];
        this.$refs.tree.setCheckedKeys([id]);

        // 获取所有选中节点id
        let idArry = this.$refs.tree.getCheckedKeys();
        let ids = "";
        idArry.forEach((ent) => {
          ids += `${ids ? "," : ""}${ent}`;
        });

        // 还原之前选中
        this.$refs.tree.setCheckedKeys([]);
        this.$refs.tree.setCheckedKeys(checkIds);
      }
      // 获取当前节点所有子节点
      this.$emit("right-Edit", this.nodeData, ids);

      this.menuVisible = true;
    },

    // 节点点击事件
    handleNodeClick(data, element, component) {
      if (
        this.showCheckbox != true &&
        this.nodeKey &&
        typeof data[this.nodeKey] !== "undefined"
      ) {
        this.$emit("input", data[this.nodeKey]);
      }
      this.$emit("node-click", {
        data,
      });
    },
    //通过node节点获取选中数据 (leafOnly, includeHalfChecked) 接收两个 boolean 类型的参数，1. 是否只是叶子节点，默认值为 false 2. 是否包含半选节点，默认值为 false
    getCheckedNodes(leafOnly=false, includeHalfChecked=false) {
      return this.$refs.tree.getCheckedNodes(leafOnly, includeHalfChecked);
    },
    //通过key获取选中数据  (leafOnly) 接收一个 boolean 类型的参数，若为 true 则仅返回被选中的叶子节点的 keys，默认值为 false
    getCheckedKeys(leafOnly) {
      return this.$refs.tree.getCheckedKeys(leafOnly);
    },
    //通过node节点设置选中数据
    setCheckedNodes(data) {
      this.$refs.tree.setCheckedNodes(data);
    },
    //通过key设置选中节点 leafOnly若为 true 则仅设置叶子节点的选中状态，默认值为 false
    setCheckedKeys(data, leafOnly) {
      this.$refs.tree.setCheckedKeys(data, leafOnly);
    },
    //重置选中
    resetChecked() {
      this.$refs.tree.setCheckedKeys([]);
    },
    // 复选框选中变化事件
    handleCheckChange(arg1, arg2, arg3) {},
    // 复选框点击事件
    handleCheck(
      checkNode,
      { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }
    ) {
      let listCheckNodeData = [];

      checkedNodes.forEach((node) => {
        if (
          node[this.myProps.children] &&
          node[this.myProps.children].length &&
          node[this.myProps.children].length > 0
        ) {
          return;
        }

        let checkedNodeData = {};
        checkedNodeData[this.nodeKey] = node[this.nodeKey];

        listCheckNodeData.push(checkedNodeData);
      });
      this.$emit("handleCheck", listCheckNodeData);
    },
  },
};
</script>

<style>
.el-main {
  padding: 0px !important;
}

.dev-type-main-left {
  overflow: auto;
  padding: 10px;
}

.right-menu {
  z-index: 1;
  position: absolute;
  height: 100px;
  width: 100px;
  padding-left: 25px;
  position: absolute;
  border-radius: 5px;
  border: 1px solid #ccc;
  background-color: white;
}

.menu-item {
  display: block;
  line-height: 20px;
  text-align: left;
  margin-top: 10px;
  font-size: 14px;
  color: #606266;
}

li:hover {
  background-color: #edf6ff;
  color: #606266;
}
/* .filter-tree {
          height: 65%;
          display: block;
          overflow-y: auto;
     } */
</style>
